using System;
using System.IO;
using System.Linq;
using HQLAddin.Highlighting.Tagger;
using HQLAddin.Tests.SnapshotUtils;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Moq;
using NUnit.Framework;
using SharpTestsEx;

namespace HQLAddin.Tests.Highlighting
{
	[TestFixture]
	public class ErrorAnalizerTest
	{
		private static readonly string[] ExampleWithBadQueries = File.ReadAllLines("examples\\example-with-badqueries.xml");

		[Test]
		public void WhenLineHasAnSpecificErrorThenMatchTextIsEqualToBadText()
		{
			var errorClassifier = new ErrorAnalizer();
			var span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(13);
			var match = errorClassifier.GetMatches(span).First();
			match.Span.GetText().Should().Be.EqualTo("where");
		}

		[Test]
		public void WhenLineHasAnSpecificErrorAndQueryStartAtTheSameLineThanQueryTagThenMatchTextIsEqualToBadText()
		{
			var errorClassifier = new ErrorAnalizer();
		    SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
		        .CreateSpanFromLineNumber(16);
		    var match = errorClassifier.GetMatches(span).First();
		    match.Span.GetText().Should().Be.EqualTo("where");
		}

		[Test]
		public void WhenLineHasErrorAndQueryStartAtSamePositionThanQueryTagThenReturnMatches()
		{
		    var errorClassifier = new ErrorAnalizer();
		    SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
		        .CreateSpanFromLineNumber(16);
		    var matches = errorClassifier.GetMatches(span);
		    matches.Count().Should().Be.EqualTo(1);
		}

		[Test]
		public void WhenLineHasErrorThenReturnMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(13);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(1);
		}

		[Test]
		public void WhenLineHasNoErrorAndQueryStartAtSamePositionThanQueryTagThenReturnNoMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(15);
			var matches = errorClassifier.GetMatches(span);
			matches.Should().Be.Empty();
		}

		[Test]
		public void WhenLineHasNoErrorThenReturnNoMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(12);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(0);
		}


		[Test]
		public void WhenCurrentLineHasErrorAndCursorIsAtTheEndOfQueryTagThanQueryTagThenReturnNoMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(14);
			var matches = errorClassifier.GetMatches(span);
			matches.Should().Be.Empty();
		}


		[Test]
		public void WhenCurrentLineHasErrorAndAllQueryIsInTheSameTagThenReturnMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(18);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(1);
			matches.First().Span.GetText().Should().Be.EqualTo("where");
		}

		[Test]
		public void WhenCurrentLineHasErrorAndAllQueryIsSurrondedByCDATAThenReturnMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(21);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(1);
			matches.First().Span.GetText().Should().Be.EqualTo("where");
		}

		[Test]
		public void WhenCurrentLineHasErrorAndAllQueryIsSurrondedByCDATAInTheSameLineThenReturnMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(29);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(1);
			matches.First().Span.GetText().Should().Be.EqualTo("where");
		}

		[Test]
		public void WhenTheQueryTagIsEmptyThenShowNoMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(31);
			var matches = errorClassifier.GetMatches(span);
			matches.Should().Be.Empty();
		}

		[Test]
		public void WhenSpanIsOutsideOfQueryTagThenReturnNoMatches()
		{
			var errorClassifier = new ErrorAnalizer();
			var span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(7);
			var matches = errorClassifier.GetMatches(span);
			matches.Should().Be.Empty();
		}

		[Test]
		public void ErrorTagTypeShouldBeEqualsToError()
		{
			var errorClassifier = new ErrorAnalizer();
			SnapshotSpan span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
				.CreateSpanFromLineNumber(29);
			var matches = errorClassifier.GetMatches(span);
			matches.Count().Should().Be.EqualTo(1);
			matches.First().Tag.ErrorType.Should().Be.EqualTo("error");
		}


		[Test]
		public void WhenLineHasAQuerySyntaxExceptionThenReturnsAnSpan()
		{
			var errorClassifier = new ErrorAnalizer();
			var span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
									.CreateSpanFromLineNumber(33);
			errorClassifier.GetMatches(span).Should().Not.Be.Empty();
		}

		[Test]
		public void WhenLineHasAQuerySyntaxExceptionThenSpanGetTextReturnsAllTheLine()
		{
			var errorClassifier = new ErrorAnalizer();
			var span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
									.CreateSpanFromLineNumber(33);
			var match = errorClassifier.GetMatches(span).First();
			match.Span.GetText().Trim().Should().Be.EqualTo("from Foo f where (");
		}

		[Test]
		public void WhenLineInitAQueryExceptionQueryThenSpansShouldBeEmpty()
		{
			var errorClassifier = new ErrorAnalizer();
			var span = SnapshotUtil.CreateSnapshot(ExampleWithBadQueries)
									.CreateSpanFromLineNumber(32);
			errorClassifier.GetMatches(span).Should().Be.Empty();
		}
	}
}